﻿//TODO: Test, FaceDetection

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using LowLevelGraphics.ColorSpaces;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// This is a filter that uses no NN (neural network)
    /// for detecting a face.
    /// </summary>
    public class FaceDetection : BaseImageFilter
    {
        /// <summary>
        /// default constructor
        /// </summary>
        public FaceDetection()
        {
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_faceDetection"></param>
        internal FaceDetection(FaceDetection _faceDetection)
        {
        }

        /// <summary>
        /// executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmap = _bitmap;

            double x1 = 0.0f;
            double y1 = 0.0f;
            double cb1 = 0.0f;
            double cr1 = 0.0f;
            double wcb = 0.0f;
            double wcr = 0.0f;

            int nHeight = bitmap.Height;
            int nWidth = bitmap.Width;

            for (int y = 0; y < nHeight; y++)
            {
                for (int x = 0; x < nWidth; x++)
                {
                    Color color = bitmap.GetPixel(x, y);
                    YCbCr ycbcr = new YCbCr(color);
                    if (ycbcr.Y < 125)
                    {
                        cb1 = 108 + (125 - ycbcr.Y) * 10 / 109;
                        cr1 = 154 - (125 - ycbcr.Y) * 10 / 109;
                        wcb = 23 + ycbcr.Y - 16 * 23.97 / 109;
                        wcr = 20 + ycbcr.Y - 16 * 18.76 / 109;
                        cb1 = (ycbcr.Cb - cb1) * 46.97 / wcb + cb1;
                        cr1 = (ycbcr.Cr - cr1) * 38.76 / wcr + cr1;
                    }
                    else if (ycbcr.Y > 188)
                    {
                        cb1 = 108 + (ycbcr.Y - 188) * 10 / 47;
                        cr1 = 154 + (ycbcr.Y - 188) * 22 / 47;
                        wcb = 14 + (235 - ycbcr.Y) * 32.97 / 47;
                        wcr = 10 + (235 - ycbcr.Y) * 28.76 / 47;
                        cb1 = (ycbcr.Cb - cb1) * 46.97 / wcb + cb1;
                        cr1 = (ycbcr.Cr - cr1) * 38.76 / wcr + cr1;
                    }
                    else
                    {
                        cb1 = ycbcr.Cb;
                        cr1 = ycbcr.Cr;
                    }

                    //TODO: Matrix Implementieren
                    //x1= [-0.819 0.574]*[cb1-109.38;cr1-152.02];
                    //y1= [-0.574 -0.819]*[cb1-109.38;cr1-152.02];

                    x1 = (-0.819 * (cb1 - 109.38)) + (0.574 * cb1 - 109.38) + (-0.819 * cr1 - 152.02) + 0.574 * (cr1 - 152.02);
                    //Todo: Matrix implementieren
                    //if (x1-1.60).^2/644.6521+(y1-2.41).^2/196.8409<=1)
                    if (Math.Pow((x1 - 1.60), 2) / 644.6521 + (Math.Pow(y1 - 2.41, 2) / 196.8409) <= 1)
                    {
                        bitmap.SetPixel(x, y, Color.White);
                    }
                    //else
                    {
                        bitmap.SetPixel(x, y, Color.Black);
                    }
                }
            }
            return bitmap;
        }

        /// <summary>
        /// create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new FaceDetection(this);
        }
    }
}
